The first step you should complete before actually stepping through this code is to install all required dependencies. Assuming you already have Anaconda installed, you'll only need to install TM1py. To do this run the following command:
pip install TM1py
You'll also need to install pystan and the facebook Prophet time series package. To do this run the following commands:
pip install pystan
pip install fbprophet
In [1]:
#import tm1 service module
from TM1py.Services import TM1Service
#import tm1 utils module
from TM1py.Utils import Utils
#import pandas
import pandas as pd
#import matplotlib
import matplotlib.pyplot as plt
#inline plotting for matplotlib
%matplotlib inline
#import statsmodels package
from fbprophet import Prophet
In [2]:
#Server address
address = 'localhost'
#HTTP port number - this can be found in your config file
port = '8892'
#username
user = 'admin'
#password
password = 'apple'
#SSL parameter - this can be found in your config file
ssl = True
The following code obtains a data set from TM1 based on the cube and view specified above. The resulting dataset is transformed into a pandas dataframe for statistical analysis.
For more on pandas and dataframes check out this pandas tutorial.
Before importing any data, create the view you would like to import into the data frame. Populate the fields below.
In [3]:
#specify the cube
cube_name = 'Retail'
#specify the view
view_name = 'Time Series'
In [4]:
with TM1Service(address= address, port=port, user=user, password=password, ssl=ssl) as tm1:
# Extract pnl data from specified cube view
raw_data = tm1.cubes.cells.get_view_content(cube_name=cube_name, view_name=view_name, private=False)
# Build pandas DataFrame fram raw cellset data
df = Utils.build_pandas_dataframe_from_cellset(raw_data, multiindex=False)
In [5]:
ts = df
ts.dtypes
ts['Date'] = ts['Year'] + '-' + ts['Period']
ts['Date'] = pd.DatetimeIndex(ts['Date'])
ts = ts.rename(columns={'Date': 'ds',
'Values': 'y'})
Rather than looping through each region and product within the data set, the following cell creates a subset of data to forecast. If you'd like to forecast for an alternate region/product combination this is where you're able to make the change by subbing out Region 13 and Product 315.
In [6]:
region = '13'
product = '315'
sub = ts[ts['Region']==region]
sub = sub[sub['Product']==product]
In [7]:
sub_model = Prophet(interval_width=0.95)
sub_model.fit(sub)
Out[7]:
In [8]:
#specify the number of future periods
future_dates = sub_model.make_future_dataframe(periods=24, freq='MS')
In [9]:
forecast = sub_model.predict(future_dates)
forecast[['ds', 'yhat', 'yhat_lower', 'yhat_upper']].tail()
Out[9]:
In [10]:
sub_model.plot(forecast,
uncertainty=True)
sub_model.plot_components(forecast)
Out[10]:
In [11]:
#Combine the forecast dataframe and our original subset
sub = sub.set_index('ds')
forecast = forecast.set_index('ds')
In [12]:
result = pd.concat([sub, forecast], axis = 1)
In [13]:
#fill out other dimensions
result['Version'] = result.Version.fillna('3')
result['Currency'] = result.Currency.fillna('Local')
result['Region'] = result.Region.fillna(region)
result['Product'] = result.Product.fillna(product)
result['Retail Measure'] = result['Retail Measure'].fillna('Sales Amount')
#make ds accessible
result = result.reset_index()
result['Year'] = pd.DatetimeIndex(result['ds']).year
result['Period'] = pd.DatetimeIndex(result['ds']).month
In [14]:
with TM1Service(address= address, port=port, user=user, password=password, ssl=ssl) as tm1:
# cellset to store the new data
cellset = {}
# Populate cellset with coordinates and value pairs
for index, row in result.iterrows():
cellset[(row['Year'], row['Period'], 'Forecast', row['Product'], row['Currency'], row['Region'],row['Retail Measure'])] = row['yhat']
tm1.cubes.cells.write_values('Retail', cellset)